//import util from "@/js/util";

const util = (function() {
	const class2type = {};
	const toString = class2type.toString;
	//空图片 作用需发挥自己强大的脑洞
	const errorImg = '';
	const offline = '网络异常，请求超时';
	//判断类型
	const type = function(obj) {
		if (obj == null) return obj + '';
		return typeof obj === 'object' || typeof obj === 'function'
			? class2type[toString.call(obj)] || 'object'
			: typeof obj;
	};
	//获取dom样式名
	const getClass = function(elem) {
		const classString = (elem.getAttribute && elem.getAttribute('class')) || '';
		if (classString) {
			return classString.replace(/[\t\r\n\f]/g, /[\s\uFEFF\xA0]/).split(/[\s\uFEFF\xA0]/) || [];
		} else {
			return [];
		}
	};
	const hasClass = function(elem, arg) {
		if (!elem || elem.nodeType == 9) {
			return false;
		}
		let flag = true;
		const args = arg.split(/[\s\uFEFF\xA0]/);
		const curClass = getClass(elem);
		each(args, function(i, v) {
			if (!curClass.includes(v)) {
				flag = false;
			}
		});
		return flag;
	};
	const setClass = function(elem, arg, flag) {
		if (!elem || elem.nodeType == 9) {
			return elem;
		}
		let newClass = [];
		const curClass = getClass(elem);
		const args = arg.split(/[\s\uFEFF\xA0]/);
		if (flag) {
			newClass = unrepeatArray(curClass, args);
		} else {
			each(curClass, function(i, v) {
				if (!args.includes(v)) {
					newClass.push(v);
				}
			});
		}
		if (newClass.length) {
			elem.setAttribute && elem.setAttribute('class', newClass.join(' '));
		}
		return elem;
	};
	//添加样式
	const addClass = function(elem, arg) {
		return setClass(elem, arg, true);
	};
	//移除样式
	const removeClass = function(elem, arg) {
		return setClass(elem, arg);
	};

	const getSearch = function(name) {
		const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i');
		let vals = window.location.search.substr(1).match(reg);
		if (vals != null) {
			return unescape(vals[2]);
		}
		return null;
	};
	//循环数组或者对象
	const each = function(obj, callback) {
		let k;
		if (type(obj) === 'object' || type(obj) === 'array') {
			for (k in obj) {
				if (callback.call(obj[k], k, obj[k]) === false) break;
			}
		}
		return obj;
	};
	//英文字母转为小写
	const strLow = function(str) {
		return type(str) === 'string' ? str.toLowerCase() : str;
	};
	//英文字母转为大写
	const strUpp = function(str) {
		return type(str) === 'string' ? str.toUpperCase() : str;
	};
	//判断是否数字，包括字符串类型的数字
	const isNumeric = function(obj) {
		return ((type(obj) === 'number' || type(obj) === 'string') && !isNaN(obj - parseFloat(obj))) || !1;
	};
	//去除前后空格
	const trim = function(text) {
		return text == null ? '' : (text + '').replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
	};
	//判断字符串、对象、数组是否为空
	const isEmpty = function(obj) {
		if (obj == null) return !0;
		switch (type(obj)) {
			case 'number':
			case 'boolean':
			case 'regexp':
			case 'error':
			case 'function':
			case 'date':
			case 'symbol':
				return !1;
			case 'string':
				return !trim(obj);
			case 'object':
				for (let k in obj) return !1;
				break;
			case 'array':
				return !obj.length;
		}
		return !0;
	};
	//拷贝对象
	const extend = function() {
		let options,
			name,
			src,
			copy,
			copyIsArray,
			clone,
			target = arguments[0] || {},
			i = 1,
			length = arguments.length,
			deep = false;
		if (type(target) === 'boolean') {
			deep = target;
			target = arguments[i] || {};
			i++;
		}
		if (type(target) !== 'object' && type(target) === 'function') {
			target = {};
		}
		if (i === length) {
			target = util;
			i--;
		}
		for (; i < length; i++) {
			if ((options = arguments[i]) != null) {
				for (name in options) {
					src = target[name];
					copy = options[name];
					if (target === copy) {
						continue;
					}
					if (deep && copy && (type(copy) == 'object' || (copyIsArray = type(copy) == 'array'))) {
						if (copyIsArray) {
							copyIsArray = false;
							clone = src && type(src) == 'array' ? src : [];
						} else {
							clone = src && type(src) == 'object' ? src : {};
						}
						target[name] = extend(deep, clone, copy);
					} else if (copy !== null) {
						target[name] = copy;
					}
				}
			}
		}
		return target;
	};
	//合并数组
	const mergeArray = function() {
		const $arr = [];
		each(arguments, (i, args) => {
			type(args) == 'array' &&
				each(args, (j, item) => {
					$arr.push(item);
				});
		});
		return $arr;
	};
	//单个或多个数组内容去重
	const unrepeatArray = function() {
		const $arr = mergeArray.apply(null, arguments);
		const $json = {},
			newArr = [];
		each($arr, (i, item) => {
			let str = JSON.stringify(item, (key, val) => {
				if (type(val) === 'function') {
					return val + '';
				}
				return val;
			});
			if (!$json[str]) {
				$json[str] = !0;
				newArr.push(item);
			}
		});
		return newArr;
	};
	//数组随机打乱顺序
	const rndArray = function(arr) {
		if (type(arr) != 'array') return arr;
		arr.sort(rndSort);
		return arr;

		function rndSort() {
			return Math.random() > 0.5 ? -1 : 1;
		}
	};
	//清除html标签
	const removeStrTag = function(str) {
		return str.replace(/<(?:.|\s)*?>/g, '');
	};
	//清除字符串中script包括其内容
	const removeStrJs = function(str) {
		return str.replace(/<script (?!src=)[\s\S]*?<\/script>/gi, '');
	};
	const getCookie = function(name) {
		let cookies = document.cookie,
			data = {},
			cookieArr;
		if (cookies != '') {
			if (cookies.indexOf(';') != -1) {
				each(cookies.split(';'), function(i, v) {
					if (v.indexOf('=') != -1) {
						cookieArr = trim(v).split('=');
						data[unescape(cookieArr.shift())] = unescape(cookieArr.join('='));
					}
				});
			} else if (cookies.indexOf('=') != -1) {
				cookieArr = trim(cookies).split('=');
				data[unescape(cookieArr.shift())] = unescape(cookieArr.join('='));
			}
		}
		return name != null ? data[name] || '' : data;
	};
	const setCookie = function(name, value, domain, storageTime) {
		let expires = '';
		if (storageTime != null) {
			let lowTime = storageTime.toLowerCase(),
				time = 1;
			each(
				{
					y: 3.1536e10,
					M: 2.592e9,
					d: 8.64e7,
					h: 3.6e6,
					m: 6e4,
					s: 1e3,
				},
				function(k, v) {
					if (lowTime.indexOf(k) > 0) {
						time = (+lowTime.split(k).shift() || 1) * v;
						return false;
					}
				}
			);
			let date = new Date();
			date.setTime(Date.now() + time);
			expires = 'expires=' + date.toUTCString() + ';';
		}
		domain = domain ? 'domain=' + domain + ';' : '';
		value = typeof value == 'object' ? JSON.stringify(value) : value;
		document.cookie = escape(name) + '=' + escape(value) + ';' + expires + domain + ' path=/';
	};
	const delCookie = function(name, domain) {
		setCookie(name, null, domain, '-1y');
	};
	const getLocal = function(name) {
		if (window.localStorage) {
			return unescape(window.localStorage[escape(name)] || '');
		} else {
			return getCookie(name);
		}
	};
	const setLocal = function(name, value, domain, storageTime) {
		if (window.localStorage) {
			window.localStorage[escape(name)] = escape(value);
		} else {
			setCookie(name, value, domain, storageTime);
		}
	};
	const delLocal = function(name, domain) {
		if (window.localStorage) {
			window.localStorage.removeItem(escape(name));
		} else {
			delCookie(name, domain);
		}
	};
	//用于判断微信中不显示title
	const showTitle = function() {
		let ua = navigator.userAgent.toLowerCase();
		return /micromessenger/.test(ua) ? true : false;
	};
	const toTen = function(time) {
		//格式化小于10的数值
		if (time >= 10) {
			return time;
		} else {
			return `0${time}`;
		}
	};
	//时间格式化日期、时间戳格式化日期、字符串格式化日期
	//time 可为date类型、时间戳类型、'2020年01月12日12时59分59秒'三种格式
	//fmt 格式为‘yyyy-MM-dd hh:mm:ss’ 默认使用‘yyyy-MM-dd’
	const timeTofmt = function(time, fmt) {
		!fmt && (fmt = 'yyyy-MM-dd');
		if (type(time) != 'date') {
			if (isNumeric(time)) {
				(time + '').length == 10 && (time += '000');
				time = new Date(parseInt(time));
			} else if (type(time) == 'string') {
				const date = new Date();
				const year = +time.substr(0, 4) || date.getFullYear();
				const month = +time.substr(5, 2) || date.getMonth();
				const day = +time.substr(8, 2) || date.getDate();
				const hour = +time.substr(11, 2) || 0;
				const minute = +time.substr(14, 2) || 0;
				const second = +time.substr(17, 2) || 0;
				time = new Date(year + '/' + month + '/' + day + ' ' + hour + ':' + minute + ':' + second);
			} else {
				return null;
			}
		}
		var o = {
			'M+': time.getMonth() + 1,
			'd+': time.getDate(),
			'h+': time.getHours(),
			'm+': time.getMinutes(),
			's+': time.getSeconds(),
			'q+': Math.floor((time.getMonth() + 3) / 3),
			S: time.getMilliseconds(),
		};
		if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (time.getFullYear() + '').substr(4 - RegExp.$1.length));
		each(o, function(k, item) {
			if (new RegExp('(' + k + ')').test(fmt)) {
				fmt = fmt.replace(RegExp.$1, RegExp.$1.length == 1 ? item : ('00' + item).substr(('' + item).length));
			}
		});
		return fmt;
	};
	//加权算法
	const weighting = function(str, factor, parity) {
		if (!factor) {
			factor = '7912356125767915842163755616'.split('');
		} else {
			if (type(factor) != 'array' && isNumeric(factor)) {
				return 0;
			}
			if (isNumeric(factor)) {
				factor = (factor + '').split('');
			}
		}
		if (!parity) {
			parity = '1098765432'.split('');
		} else {
			if (type(parity) != 'array' && type(parity) != 'string') {
				return 0;
			}
			if (type(parity) != 'string') {
				parity = parity.split('');
			}
		}
		//转字符串
		str += '';
		let sum = 0;
		each(str.split(''), function(i, v) {
			if (isNumeric(v)) {
				let a = +v;
				let f = +factor[i % factor.length];
				sum += a * f;
			}
		});
		return parity[sum % parity.length];
	};
	//判断id是否真实有效
	const hasid = function(str) {
		const ids = (str + '').replace(/[^0-9]/gi, '');
		const id = ids.substr(0, ids.length - 1);
		const val = ids.substr(-1);
		const ws = weighting(id);
		if (ws == val) {
			return true;
		} else {
			return false;
		}
	};
	// id加权加密解密使用方法
	// const id = 1;
	// const encid = util.encid(id);
	// const decid = util.decid(encid);
	// const hasid = util.hasid(encid);
	// console.log("id加密前：" + id);
	// console.log("id加密后：" + encid);
	// console.log("id解密后：" + decid);
	// console.log("判断加密id是否有效：" + hasid);
	//加密id
	const encid = function(id, spills, digit) {
		if (!spills && type(spills) != 'array' && type(spills) != 'string') {
			spills = 'YDWQMSJEBA';
		}
		if (type(spills) == 'string') {
			spills = spills.split('');
		}
		if (!digit || digit < 1e7) {
			digit = 9638052741;
		} else {
			digit = Number(digit);
		}
		id = Number(id) || 0;
		let first = spills[0];
		let spill = 0;
		if (id > digit) {
			spill = (id / digit) | 0;
			const spillObj = [];
			each((spill + '').split(''), (i, v) => {
				spillObj.push(spills[+v]);
			});
			first = spillObj.join('');
		}
		let val = id;
		if (spill != 0) {
			val -= spill * digit;
		}
		const len = (digit + '').length;
		const str = new Array(len + 1).join('0');
		let newId = (str + val).substr(-len);
		//加权码
		const ws = weighting(newId);
		return first + newId + ws;
	};
	//解密id
	const decid = function(str, spills, digit) {
		if (!hasid(str)) {
			return '0';
		}
		if (type(spills) != 'array' || type(spills) != 'string') {
			spills = 'YDWQMSJEBA';
		}
		if (type(spills) == 'string') {
			spills = spills.split('');
		}
		if (!digit || digit < 1e7) {
			digit = 9638052741;
		} else {
			digit = Number(digit);
		}
		const spill = str.replace(/[^a-z]+/gi, '');
		const ids = str.replace(/[^0-9]/gi, '');
		let spillTotal = '';
		each((spill + '').split(''), (i, v) => {
			spillTotal += spills.indexOf(v);
		});
		const total = +spillTotal * digit;
		return total + +ids.substr(0, ids.length - 1);
	};
	// tips：多用于身份证、银行卡、手机号码 ----君子操作，实际上可改装任何字符串。
	// id卡加密 （例如：362******8427 = util.idcardEnc(36241234567898427, 3, 4, 6)）
	// str(卡号), first(前面暴露显示的位数,默认3), last（后面暴露显示的位数,默认4）, star（*的位数,默认字符串长度-first-last）
	// starTxt 特殊需要的时候可修改标记
	const idcardEnc = function(str, first, last, star, starTxt) {
		if (!str) {
			return '';
		}
		str += '';
		if (!Number(first)) {
			first = 3;
		} else {
			first = +first;
		}
		if (!Number(last)) {
			last = 4;
		} else {
			last = +last;
		}
		if (Number(star)) {
			star = +star;
		}
		//正则写法
		//const reg = /^(\d{4})\d+(\d{4})$/; //已验证 str.replace(reg, "$1**********$2");
		//const reg = new RegExp('([A-Za-z0-9]{' + first + '})[A-Za-z0-9]+([A-Za-z0-9]{' + last + '})'); //已验证
		//const reg = new RegExp('([d+]{' + first + '})[d+]+([d+]{' + last + '})'); //未验证
		const end = str.length - first - last; //字符串非暴露数量
		if (end > 0) {
			first = str.substr(0, first);
			last = str.substr(-last);
			star = new Array((star || end) + 1).join(starTxt || '*');
			return first + star + last;
		} else {
			return str;
		}
	};
	//判断银行卡是否真实有效
	const isBankCard = function(card) {
		//转字符串
		card += '';
		//取银行卡最后一位效验码
		const last = card.substr(-1); //效验码
		//取银行卡真实卡号
		const first = card.substr(0, card.length - 1);
		//用于叠加真实卡号的算法总和
		let sum = 0;
		//把真实卡号转成数组，并且取反
		each(first.split('').reverse(), (i, v) => {
			//判断是否为数字
			if (!isNumeric(v)) {
				return;
			}
			//取得偶数位
			if (i % 2) {
				//叠加偶数位值，算出总和
				sum += Number(v);
			} else {
				//叠加奇数值 * 2，算出总和
				let s = Number(v) * 2;
				//判断奇数位的两倍的值是否大于10
				//如果大于10，则拆分成个位+十位的结果
				//再进行叠加算出总和
				each((s + '').split(''), (j, m) => {
					sum += Number(m);
				});
			}
		});
		//判断真实卡号的算法总和 + 最后一位效验码
		//必须整除10，才能表示该银行卡为真实有效
		return (sum + Number(last)) % 10 == 0;
	};
	//格式化金额 n = 小数点后面保留几位
	const moneyToStr = function(val, n) {
		n = isNumeric(n) ? +n : 2;
		if (!val) {
			return '0.' + ('0' + Array(n).join('0'));
		}
		let vals = parseFloat((val + '').replace(/[^\d.-]/g, ''))
			.toString()
			.split('.');
		let intVal = (vals[0] + '').replace(/(\d)(?=(?:\d{3})+$)/g, '$1,');
		let floatVal = ((vals[1] || '0') + Array(n).join('0')).slice(0, n);
		return [intVal, floatVal].join('.');
	};
	// 格式化两数相减精度问题
	const subtrAccuracy = function(arg1, arg2) {
		var r1, r2, m, n;
		try {
			r1 = arg1.toString().split('.')[1].length;
		} catch (e) {
			r1 = 0;
		}
		try {
			r2 = arg2.toString().split('.')[1].length;
		} catch (e) {
			r2 = 0;
		}
		m = Math.pow(10, Math.max(r1, r2));
		//动态控制精度长度
		n = r1 >= r2 ? r1 : r2;
		return ((arg1 * m - arg2 * m) / m).toFixed(n);
	};
	//打开新窗口
	const createBlank = function(url, name) {
		if (!url) {
			alert('新开窗口链接不存在');
		}
		const a = document.createElement('a');
		a.target = '_blank';
		if (name) {
			a.setAttribute('download', name);
		}
		a.href = url;
		if (document.createEvent) {
			var evt = document.createEvent('MouseEvents');
			evt.initEvent('click', true, true);
			a.dispatchEvent(evt);
		} else if (a.fireEvent) {
			a.fireEvent('onclick');
		} else if (a.click) {
			if (typeof a.onclick == 'function') {
				a.onclick({
					type: 'click',
				});
				a.click();
			} else {
				window.open(url, '_blank');
			}
		} else {
			window.open(url, '_blank');
		}
	};
	//正则各种规则，最终转换为 key = function(str) { return reg.test(str)}
	const regs = {
		password: /^([a-zA-Z0-9]|[._]){8,20}$/,
		//判断是否手机号码
		///^0?(13[0-9]|15[012356789]|16[567]|17[0123678]|18[0-9]|14[57]|19[89])[0-9]{8}$/
		isTel: /^0?(1[3456789])[0-9]{9}$/, //开通全网段任何正常和非正常手机号码验证
		//判断是否邮箱格式
		isEmail: /^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/,
		//银行卡
		isIdCard: /^([1-9]{1})(\d{15,18})$/,
		//判断是否整数
		isIntpat: /^-?\d+$/,
		//数字验证，包含正负、小数
		isNumpat: /^-?\d*\.?\d+$/,
		//简单验证身份证信息
		isIdcode: /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/,
		//网址
		isUrl: /^(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/,
		//ipv4
		isIpv4: /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,
		//ipv6
		isIpv6: /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/,
		//rgb hex验证
		isHex: /^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/,
		//日期 2000-01-01
		isDate: /^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$/,
		//QQ
		isQQ: /^[1-9][0-9]{4,}$/,
		//微信
		isWeChat: /^[a-zA-Z]([-_a-zA-Z0-9]{5,19})+$/,
		//华夏车牌号
		isCarpat: /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-Z0-9]{4}[A-Z0-9挂学警港澳]{1}$/,
		//纯中文
		isCn: /^[\u4E00-\u9FA5]+$/,
		//纯英文
		isEn: /^[a-zA-Z]+$/,
	};
	//转换上面的规则，最终转换为 key = function(str) { return reg.test(str)}
	const regFn = function() {
		let $json = {};
		each(regs, (k, v) => {
			$json[k] = (str) => {
				return (str && v.test(str)) || !1;
			};
		});
		return $json;
	};

	/**
	 * @param {Number} value 输入值
	 * @param {Function} callback 回调函数
	 * @param {Number} max 最大值
	 * @param {Number} min 最小值
	 */
	const limitSize = function(value, callback, max = 100, min = 0) {
		if (+value > max) {
			value = max;
		}
		if (+value < +min) {
			value = min;
		}
		callback(value);
	};

	//内置方法，得到所有类型
	each(
		['Boolean', 'Number', 'String', 'Function', 'Array', 'Date', 'RegExp', 'Object', 'Error', 'Symbol'],
		(i, name) => {
			class2type['[object ' + name + ']'] = strLow(name);
		}
	);

	return extend(
		{},
		{
			type,
			each,
			trim,
			hasid,
			encid,
			decid,
			toTen,
			strLow,
			strUpp,
			extend,
			offline,
			isEmpty,
			hasClass,
			addClass,
			errorImg,
			rndArray,
			getLocal,
			setLocal,
			delLocal,
			getSearch,
			idcardEnc,
			weighting,
			showTitle,
			getCookie,
			setCookie,
			delCookie,
			isNumeric,
			timeTofmt,
			isBankCard,
			moneyToStr,
			subtrAccuracy,
			mergeArray,
			removeClass,
			createBlank,
			removeStrJs,
			removeStrTag,
			unrepeatArray,
			limitSize,
		},
		regFn()
	);
})();

export default util;
